package com.example.demo.common.smt;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Aspect
@Component
public class BatchInsertAspect {
    @Pointcut("@annotation(com.example.demo.common.smt.BatchInsert)")
    public void batchInsertPointcut() {
    }



    @Around("batchInsertPointcut() && args(tenantId, data)")
    public <T> int  afterBatchInsert(JoinPoint joinPoint, String tenantId, List<T> data) throws Exception {
        Method method = getTargetMethod(joinPoint);
        BatchInsert annotation = method.getAnnotation(BatchInsert.class);
        int batchSize = annotation.batchSize();
        int threadCount = annotation.threadCount();

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        // 获取总数据量
        int totalItems = data.size();
        try {
            for (int i = 0; i < totalItems; i += batchSize) {
                int endIndex = Math.min(i + batchSize, totalItems);
                List<T> batch = data.subList(i, endIndex);

                executorService.submit(() -> {
                    try {
                        method.invoke(joinPoint.getTarget(), tenantId, batch);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }

        } finally {
            // 关闭线程池
            executorService.shutdown();
        }

        // 返回插入的总行数
        return totalItems;
    }

    private Method getTargetMethod(JoinPoint joinPoint) throws NoSuchMethodException {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = methodSignature.getMethod();
        return targetMethod;
    }
}